package com.yunbiao.ybbusstopplate.serialport.agreement;

import android.text.TextUtils;
import android.util.Log;

import com.blankj.utilcode.util.ConvertUtils;
import com.blankj.utilcode.util.Utils;
import com.yunbiao.ybbusstopplate.bean.SiteInfoBean;
import com.yunbiao.ybbusstopplate.utils.BytesUtils;
import com.yunbiao.ybbusstopplate.utils.StringUtils;

import java.util.ArrayList;
import java.util.Deque;
import java.util.LinkedList;
import java.util.List;
import java.util.Objects;
import java.util.Queue;

import io.reactivex.Observable;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.Disposable;
import io.reactivex.functions.Consumer;
import io.reactivex.functions.Function;
import io.reactivex.schedulers.Schedulers;

public class LSTKPortAgreement extends BaseAgreement {
    private static final String TAG = "LSPortAgreement2";
    private static LSTKPortAgreement lsPortAgreement2;
    private final ListResolver listResolver;
    private final AgreementDataTool dataTool;
    private LSTKPortAgreement(){
        dataTool = new AgreementDataTool();
        dataTool.setSHex("aa");
        dataTool.setEHex("55");
        dataTool.setDataReceive(new AgreementDataTool.AgreementDataReceive() {
            @Override
            public void onDataReceive(byte[] datas) {
                if(datas == null || datas.length == 0){
                    return;
                }

                choice(datas);
            }
        });
        listResolver = new ListResolver((lineName, upList, downList) -> {
            //站点列表
            if(agreementListener != null){
                agreementListener.onSiteListResult(upList);
                agreementListener.onLineInfoResult(new String[]{lineName,upList.get(0),upList.get(upList.size()-1)});
            }
        });
    }

    public static LSTKPortAgreement getInstance(){
        if (lsPortAgreement2 == null){
            lsPortAgreement2 = new LSTKPortAgreement();
        }
        return lsPortAgreement2;
    }

    public void analyzeData(byte[] bytes){
        dataTool.handleData(bytes);
    }

    private void choice(byte[] datas) {
        try {
            byte start = datas[0];
            byte address = datas[1];
            byte addr = datas[2];
            byte length = datas[3];
            byte order = datas[4];
            switch (order) {
                case (byte)0x01:
                    upDown(datas);
                    break;
                case (byte)0x22:
                    broad(datas);
                    break;
                case (byte)0x24:
                    list(datas);
                    break;
            }

        } catch (Exception e){
            e.printStackTrace();
            if (agreementListener!=null){
                agreementListener.agreementFailed();
            }
        }
    }

    private void upDown(byte[] bytes){
        Deque<Byte> byteQueue = new LinkedList<>();
        for (byte aByte : bytes) {
            byteQueue.offer(aByte);
        }

        //跳过基础数据
        for (int i = 0; i < 5 + 16 + 6; i++) {
            byteQueue.poll();
        }

        Byte poll = byteQueue.poll();
        String bits = ConvertUtils.bytes2Bits(new byte[]{poll});

        String upDown = bits.substring(bits.length() - 1);
        if(agreementListener != null){
            ArrayList<String> list = null;
            if(TextUtils.equals("0",upDown)){
                list = new ArrayList<>(listResolver.upSiteList);
            } else if(TextUtils.equals("1",upDown)){
                list = new ArrayList<>(listResolver.downSiteList);
            }

            if(list != null){
                agreementListener.onSiteListResult(list);
                agreementListener.onLineInfoResult(new String[]{listResolver.lineName,list.get(0),list.get(list.size()-1)});
            }
        }


        Log.d(TAG, "upDown: " + bits);

    }

    private void broad(byte[] bytes){
        // AA A0 5F 25 22
        // 00 //保留
        // 03 //站序号 Bit7=1 离站 bit7=0到站 bit0-6站点序号
        // 19 3C 52 3E B3 CB BF CD C3 C7 A3 AC B0 CB BB A7 B6 AB BF DA B5 BD C1 CB A3 A1 02 03
        // 0A 39 12 55
        byte aByte = bytes[6];

        String bits = ConvertUtils.bytes2Bits(new byte[]{aByte});
        Log.e(TAG, "broad: " + bits);

        String inOut = bits.substring(0,1);
        String indexStr = bits.substring(1, bits.length());
        byte[] indexBytes = ConvertUtils.bits2Bytes("0" + indexStr);
        int index = BytesUtils.hex16to10(BytesUtils.bytesToHex(indexBytes));

        Log.d(TAG, "broad: 站点序号：" + index);
        Log.d(TAG, "broad: " + (Objects.equals(inOut, "1") ? "离站" : "到站"));

        SiteInfoBean siteInfoBean = new SiteInfoBean();
        if(TextUtils.equals("0",inOut)){//到站
            siteInfoBean.setStutas(1);
            siteInfoBean.setIndex(index - 1);
        } else if(TextUtils.equals("1",inOut)){//离站
            siteInfoBean.setStutas(0);
            siteInfoBean.setIndex(index);
        }
        if(agreementListener != null){
            siteInfoBean.setSiteName("");
            agreementListener.onSiteTipResult(siteInfoBean);
        }
    }

    private void list(byte[] bytes){
        //如果该解析器是完整的，则直接重置
        listResolver.resolve(bytes);
    }

    private static class ListResolver {
        private final List<Byte> dataList;

        private final ArrayList<String> upSiteList;

        private String lineName;

        private final ArrayList<String> downSiteList;

        private final OnSiteListCompleteCallback onSiteListCompleteCallback;

        public ListResolver(OnSiteListCompleteCallback onSiteListCompleteCallback) {
            this.onSiteListCompleteCallback = onSiteListCompleteCallback;

            this.dataList = new LinkedList<>();

            this.lineName = "";

            this.upSiteList = new ArrayList<>();

            this.downSiteList = new ArrayList<>();
        }

        public void resolve(byte[] bytes) {
            //转换为队列
            Deque<Byte> byteQueue = new LinkedList<>();
            for (byte aByte : bytes) {
                byteQueue.offer(aByte);
            }

            //跳过基础数据
            for (int i = 0; i < 5; i++) {
                byteQueue.poll();
            }

            //跳过末尾
            for (int i = 0; i < 3; i++) {
                byteQueue.pollLast();
            }

            //包序号
            byte packNumByte = byteQueue.poll();
            int packNum = BytesUtils.hex16to10(BytesUtils.byteToHex(packNumByte));
            Log.d(TAG, "list: 包序号：" + packNum);

            if (packNum == 0) {

                this.lineName = "";
                this.upSiteList.clear();
                this.downSiteList.clear();
                this.dataList.clear();

                //跳过15字节
                for (int i = 0; i < 15; i++) {
                    byteQueue.poll();
                }
            } else {
                //跳过1字节
                byteQueue.poll();
            }

            //加入总数据包
            this.dataList.addAll(byteQueue);

            //开始解析
            resolve(this.dataList, new Consumer<Boolean>() {
                @Override
                public void accept(Boolean aBoolean) throws Exception {
                    if(aBoolean && onSiteListCompleteCallback != null){
                        onSiteListCompleteCallback.onComplete(lineName,upSiteList,downSiteList);
                    }
                }
            });
        }

        private Disposable disposable;

        private void resolve(List<Byte> list, Consumer<Boolean> resultConsumer) {
            if (disposable != null && !disposable.isDisposed()) {
                disposable.dispose();
                disposable = null;
            }
            Queue<Byte> thisDataQueue = new LinkedList<>(list);
            disposable = Observable
                    .just(thisDataQueue)
                    .map(byteQueue -> {
                        String lName = "";

                        int uTotal = -1;
                        List<String> uL = new ArrayList<>();

                        int dTotal = -1;
                        List<String> dL = new ArrayList<>();

                        int length = -1;
                        while (!byteQueue.isEmpty()) {
                            if (uTotal == -1) {
                                //上行总数为-1则解析上行总数
                                int uTotalLength = BytesUtils.hex16to10(BytesUtils.byteToHex(byteQueue.poll()));
                                byte[] bytes = new byte[uTotalLength];
                                for (int i = 0; i < bytes.length; i++) {
                                    bytes[i] = byteQueue.poll();
                                }
                                uTotal = BytesUtils.hex16to10(BytesUtils.bytesToHex(bytes));
                                Log.d(TAG, "resolve: 上行总数：" + uTotalLength + " ----------");

                                //跳过4位保留字节
                                for (int i = 0; i < 4; i++) {
                                    byteQueue.poll();
                                }
                                Log.d(TAG, "resolve: 跳过4位保留字节");

                                //线路名
                                int lineNameLength = BytesUtils.hex16to10(BytesUtils.byteToHex(byteQueue.poll()));
                                byte[] lineNameBytes = new byte[lineNameLength];
                                for (int i = 0; i < lineNameBytes.length; i++) {
                                    lineNameBytes[i] = byteQueue.poll();
                                }
                                lName = StringUtils.hexStringToString(BytesUtils.bytesToHex(lineNameBytes));
                                Log.d(TAG, "resolve: 线路名");
                            } else if (uL.size() != uTotal) {
                                //上行列表不完整解析上行列表
                                if (length == -1) {
                                    length = BytesUtils.hex16to10(BytesUtils.byteToHex(byteQueue.poll()));
                                    Log.d(TAG, "resolve: 站名长度：" + length);
                                } else {
                                    byte[] bytes = new byte[length];
                                    for (int i = 0; i < bytes.length; i++) {
                                        bytes[i] = byteQueue.poll();
                                    }
                                    String siteName = StringUtils.hexStringToString(BytesUtils.bytesToHex(bytes));
                                    uL.add(siteName);
                                    Log.d(TAG, "resolve: 站名：" + siteName);
                                    length = -1;
                                }
                            } else if (dTotal == -1) {
                                //抛弃一位（83）
                                byteQueue.poll();

                                //上行总数为-1则解析上行总数
                                int dTotalLength = BytesUtils.hex16to10(BytesUtils.byteToHex(byteQueue.poll()));
                                byte[] bytes = new byte[dTotalLength];
                                for (int i = 0; i < bytes.length; i++) {
                                    bytes[i] = byteQueue.poll();
                                }
                                dTotal = BytesUtils.hex16to10(BytesUtils.bytesToHex(bytes));
                                Log.d(TAG, "resolve: 下行总数：" + dTotal + " ----------");

                                //跳过4位保留
                                for (int i = 0; i < 4; i++) {
                                    byteQueue.poll();
                                }
                                Log.d(TAG, "resolve: 跳过4位保留字节");

                                //跳过线路名
                                for (int i = 0; i < 4; i++) {
                                    byteQueue.poll();
                                }
                                Log.d(TAG, "resolve: 跳过4位线路号");
                            } else if (dL.size() != dTotal) {
                                //下行列表不完整解析下行列表
                                if (length == -1) {
                                    length = BytesUtils.hex16to10(BytesUtils.byteToHex(byteQueue.poll()));
                                    Log.d(TAG, "resolve: 站名长度：" + length);
                                } else {
                                    byte[] bytes = new byte[length];
                                    for (int i = 0; i < bytes.length; i++) {
                                        bytes[i] = byteQueue.poll();
                                    }
                                    String siteName = StringUtils.hexStringToString(BytesUtils.bytesToHex(bytes));
                                    dL.add(siteName);
                                    Log.d(TAG, "resolve: 站名：" + siteName);
                                    length = -1;
                                }
                            }
                        }

                        boolean isComplete = (uTotal != -1 && uL.size() == uTotal) && (dTotal != -1 && dL.size() == dTotal);
                        if (isComplete) {
                            Log.d(TAG, "resolve: 解析完成");
                            lineName = lName;

                            upSiteList.addAll(uL);

                            downSiteList.addAll(dL);
                        }
                        return isComplete;
                    })
                    .subscribeOn(Schedulers.single())
                    .observeOn(AndroidSchedulers.mainThread())
                    .subscribe(resultConsumer, throwable -> {

                    });
        }

        public interface OnSiteListCompleteCallback{
            void onComplete(String lineName,ArrayList<String> upList,ArrayList<String> downList);
        }
    }

    private boolean b = true;
    public void testBroad(){
        String s;
        if(b){
            s = "AA A0 5F 25 22 00 03 19 3C 52 3E B3 CB BF CD C3 C7 A3 AC B0 CB BB A7 B6 AB BF DA B5 BD C1 CB A3 A1 02 03 0A 39 12 55";
        } else {
            s = "AA A0 5F 53 22 00 83 47 3C 59 3E B3 CB BF CD C3 C7 A3 AC CF C2 D2 BB D5 BE CD F5 BC D2 CE F1 B4 E5 B6 AB A1 A3 D4 F6 C7 BF B0 B2 C8 AB D2 E2 CA B6 A3 AC CF FB B3 FD BB F0 D4 D6 D2 FE BB BC A3 AC B9 B9 BD A8 BA CD D0 B3 C9 E7 BB E1 A1 A3 02 03 0A 7F 37 55";
        }
        b = !b;
        s = s.replaceAll(" ","");
        byte[] bytes = BytesUtils.hexToByteArray(s);
        analyzeData(bytes);
    }

    public void testList(){
        //11站
        String s1 = "AA 97 68 88 24 " +
                "00 " +//包序号
                "00 5E AD 08 08 00 09 15 13 03 0D 00 90 01 83 " +//忽略15字节
                "01 2E " +//站名总数长度+站名总数（46站）
                "00 00 00 00 " +//保留字节
                "03 32 30 35 " + //线路号长度+线路号
                "08 D6 E9 B9 E2 D3 F9 BE B0 " +
                "0C CF E3 B3 C7 DB AA C9 E1 CE F7 C3 C5 " +
                "08 CE EF C3 C0 B3 AC CA D0 " +
                "04 C8 FD D6 D0 " +
                "06 BC C6 C9 FA BE D6 " +
                "08 D0 C2 BB AA BC CE D4 B0 " +
                "04 B9 E3 B3 A1 " +
                "08 CA A2 B4 EF B2 AC B9 AC " +
                "0A B2 BD D0 D0 BD D6 B6 AB BF DA " +
                "08 C8 CB C3 F1 D2 BD D4 BA " +
                "06 BB AA C1 AA CE F7 " +
                "0A D0 C2 BB A8 D4 B0 CA D0 B3 A1 " +
                "BC 4C 55";//校验位+结尾
        //16站
        String s2 = "AA 97 68 88 24 " +
                "01 " +//包序号
                "00 " +//？？？
                "08 D2 E6 C3 F1 D2 F8 D0 D0 " +
                "0A CC EC C7 D9 CD E5 D0 A1 C7 F8 " +
                "0A BA C3 B0 D9 C4 EA CE F7 C3 C5 " +
                "06 D1 C7 CC AB B3 C7 " +
                "04 C1 F5 D7 AF " +
                "04 D5 D4 CD CD " +
                "04 B3 D8 CD CD " +
                "0E D2 B6 CD CD C2 B7 D5 FE D6 B4 B7 A8 B6 D3 " +
                "08 CB AB B0 B2 D0 C2 B3 C7 " +
                "04 C7 AF CD CD " +
                "04 BC D6 D7 AF " +
                "06 C7 B0 D1 D3 CB C2 " +
                "06 C0 EE D0 C1 D7 AF " +
                "06 CA AE B0 D9 BB A7 " +
                "06 CB EF D0 A1 D3 AA " +
                "08 CB AB B0 B2 BC DD D0 A3 " +
                "06 CE F7 BF 28 59 55";//长度？？？解析乱码？？？
        //14站（上行总数41站）
        String s3 = "AA 97 68 88 24 " +
                "02 " +//包序号
                "00 DA CD B7 " +//？？？
                "06 B1 B1 BF DA CD B7 " +
                "06 B6 AB BF DA CD B7 " +
                "06 BA AB D3 AA D7 AF " +
                "06 D1 EE D3 AA D7 AF " +
                "0A B9 FA B0 B2 CF DF C2 B7 BF DA " +
                "06 CB EF D3 AA D7 AF " +
                "06 D5 D4 D3 AA D7 AF " +
                "0A B9 CB BC D2 CD CD B4 E5 BF DA " +
                "06 CC AB C6 BD D7 AF " +
                "06 D0 A1 C1 F5 D7 AF " +
                "10 B9 FA B0 B2 D1 B5 C1 B7 BB F9 B5 D8 C2 B7 BF DA " +
                "06 B5 C2 D0 C1 D7 AF " +
                "06 CD F5 BC D2 CE F1 " +
                "0A CD F5 BC D2 CE F1 B4 E5 B6 AB " +
                "08 B0 CB BB A7 D6 59 55";//长度少一位？？？校验位和结尾？？？
        String s4 = "AA 97 68 88 24 " +
                "03 " +//包序号
                "00 B6 AB BF DA 06 B3 CC B9 D9 CD CD 04 D6 D0 D3 AA " +//？？？
                "83 " +//保留
                "01 2E " +//站点总数长度+站点总数
                "00 00 00 00 " +//保留
                "03 32 30 35 " +//线路名长度+线路名
                "04 D6 D0 D3 AA " +
                "06 B3 CC B9 D9 CD CD " +
                "08 B0 CB BB A7 B6 AB BF DA " +
                "0A CD F5 BC D2 CE F1 B4 E5 B6 AB " +
                "06 CD F5 BC D2 CE F1 " +
                "06 B5 C2 D0 C1 D7 AF " +
                "10 B9 FA B0 B2 D1 B5 C1 B7 BB F9 B5 D8 C2 B7 BF DA " +
                "06 D0 A1 C1 F5 D7 AF " +
                "06 CC AB C6 BD D7 AF " +
                "0A B9 CB BC D2 CD CD B4 E5 BF DA " +
                "06 D5 D4 D3 AA D7 AF " +
                "06 CB EF D3 AA D7 9C " +
                "53 55";//校验长度？？？
        String s5 = "AA 97 68 88 24 " +
                "04 " +//包序号
                "00 AF " +//？？？
                "0A B9 FA B0 B2 CF DF C2 B7 BF DA " +
                "06 D1 EE D3 AA D7 AF " +
                "06 BA AB D3 AA D7 AF " +
                "06 B6 AB BF DA CD B7 " +
                "06 B1 B1 BF DA CD B7 " +
                "06 CE F7 BF DA CD B7 " +
                "08 CB AB B0 B2 BC DD D0 A3 " +
                "06 CB EF D0 A1 D3 AA " +
                "06 CA AE B0 D9 BB A7 " +
                "06 C0 EE D0 C1 D7 AF " +
                "06 C7 B0 D1 D3 CB C2 " +
                "04 BC D6 D7 AF " +
                "04 C7 AF CD CD " +
                "08 CB AB B0 B2 D0 C2 B3 C7 " +
                "0E D2 B6 CD CD C2 B7 D5 FE D6 B4 B7 A8 B6 D3 " +
                "04 B3 D8 CD CD " +
                "04 D5 D4 CD CD " +
                "5A 57 55";
        String s6 = "AA 97 68 88 24 " +
                "05 " +//包序号
                "00 " +//？？？
                "04 C1 F5 D7 AF " +
                "06 D1 C7 CC AB B3 C7 " +
                "0A BA C3 B0 D9 C4 EA CE F7 C3 C5 " +
                "0A CC EC C7 D9 CD E5 D0 A1 C7 F8 " +
                "08 D2 E6 C3 F1 D2 F8 D0 D0 " +
                "0A D0 C2 BB A8 D4 B0 CA D0 B3 A1 " +
                "06 BB AA C1 AA CE F7 " +
                "08 C8 CB C3 F1 D2 BD D4 BA " +
                "0A B2 BD D0 D0 BD D6 B6 AB BF DA " +
                "08 CA A2 B4 EF B2 AC B9 AC " +
                "04 B9 E3 B3 A1 " +
                "08 D0 C2 BB AA BC CE D4 B0 " +
                "06 BC C6 C9 FA BE D6 " +
                "04 C8 FD D6 D0 " +
                "08 CE EF C3 C0 B3 AC CA D0 " +
                "0C CF E3 F2 59 55";//长度？？？
        String s7 = "AA 97 68 1B 24 " +
                "06 " +//包序号
                "00 B3 C7 DB AA C9 E1 CE F7 C3 C5 " +//？？？
                "08 D6 E9 B9 E2 D3 F9 BE B0 " +
                "D6 0F 55";

        String[] strings = {s1,s2,s3,s4,s5,s6,s7};
        for (String string : strings) {
            String s = string.replaceAll(" ","");
            byte[] bytes = BytesUtils.hexToByteArray(s);
            analyzeData(bytes);
        }
    }

    private boolean b1 = true;
    public void testUpDown(){
        String s1;
        if(b1){
            s1 = "AA 60 9F 24 01 32 30 35 20 20 20 20 20 20 20 20 20 20 20 20 20 06 17 07 02 03 23 10 20 AC 00 00 00 00 00 83 04 55";
        } else {
            s1 = "AA 60 9F 24 01 32 30 35 20 20 20 20 20 20 20 20 20 20 20 20 20 59 16 07 02 03 23 11 20 AC 00 00 00 00 00 D6 04 55";
        }
        b1 = !b1;

        s1 = s1.replaceAll(" ","");
        byte[] bytes = BytesUtils.hexToByteArray(s1);
        analyzeData(bytes);
    }
}
